home *** CD-ROM | disk | FTP | other *** search
/ Saar AMOK 2 / Saar AMOK II - Oktober 1994 (1994)(Kreativ Marketing)(DE)[!][I-7598].iso / disks / 651_700 / 652 / xpkdisk / source.lha / xdclear.c < prev    next >
C/C++ Source or Header  |  1993-11-08  |  13KB  |  598 lines

  1. /*
  2.  * On a clear disk you can seek forever...
  3.  *
  4.  * Clear out all unused blocks on a disk, and if a whole track is
  5.  * unused, delete the appropriate track file.
  6.  *
  7.  * $Id: xdclear.c,v 1.1 1993/11/08 13:23:03 Rhialto Rel $
  8.  * $Log: xdclear.c,v $
  9.  * Revision 1.1  1993/11/08  13:23:03  Rhialto
  10.  * Initial revision
  11.  *
  12.  *
  13.  * (C) Copyright 1993 by Olaf 'Rhialto' Seibert. All rights reserved.
  14.  */
  15.  
  16. #include "xpkdisk.h"
  17.  
  18. #include <stdio.h>
  19. #include <string.h>
  20. #include <stdlib.h>
  21. #include <dos/dos.h>
  22. #include <dos/filehandler.h>
  23.  
  24. extern struct DosLibrary *DOSBase;
  25. extern struct ExecBase *SysBase;
  26.  
  27. struct FileSysStartupMsg Fssm;
  28. struct DosEnvec De;
  29. struct IOExtTD *Io;
  30. struct MsgPort *Port;
  31. struct MsgPort *HandlerPort;
  32. ULONG        MaxKey;
  33. ULONG        RootBlockKey;
  34. ULONG           *RootBlock;
  35. ULONG        BitsPerBitmapBlock;
  36. ULONG        BMBlocksPerBitmapExtBlock;
  37. ULONG        BitmapBlockNr = -2;
  38. ULONG           *BitmapBlock;
  39. ULONG        BitmapExtBlockNr = -1;
  40. ULONG           *BitmapExtBlock;
  41. ULONG           *ZeroBlock;
  42. ULONG        Offset;
  43. int        XpkDisk;
  44. int        Pretend;
  45. int        Verbose;
  46.  
  47. int        SectorsCleared;
  48. int        SectorsReallyCleared;
  49. int        TracksDeleted;
  50. int        TracksReallyDeleted;
  51.  
  52. #define debug(x)    printf x
  53. #define debug0(x)
  54.  
  55. #define SIZE    De.de_SizeBlock
  56.  
  57. #define BM_BLOCKS_PER_ROOTBLOCK     ((-25)-(-49)+1)
  58. #define BM_BLOCKS_PER_BMEBLOCK        (SIZE - 1)
  59.  
  60. int
  61. GetKey(ULONG key, ULONG *buffer)
  62. {
  63.     Io->iotd_Req.io_Command = ETD_READ;
  64.     Io->iotd_Req.io_Offset = Offset + sizeof(ULONG) * SIZE * key;
  65.     Io->iotd_Req.io_Length = sizeof(ULONG) * SIZE;
  66.     Io->iotd_Req.io_Data = (char *)buffer;
  67.  
  68.     if (DoIO((struct IORequest *)Io)) {
  69.     printf("Read error %d on sector %d!\n",
  70.         Io->iotd_Req.io_Error, key);
  71.     return Io->iotd_Req.io_Error;
  72.     }
  73.     return 0;
  74. }
  75.  
  76. int
  77. PutKey(ULONG key, ULONG *buffer)
  78. {
  79.     Io->iotd_Req.io_Command = ETD_WRITE;
  80.     Io->iotd_Req.io_Offset = Offset + sizeof(ULONG) * SIZE * key;
  81.     Io->iotd_Req.io_Length = sizeof(ULONG) * SIZE;
  82.     Io->iotd_Req.io_Data = (char *)buffer;
  83.  
  84.     if (DoIO((struct IORequest *)Io)) {
  85.     printf("Write error %d on sector %d!\n",
  86.         Io->iotd_Req.io_Error, key);
  87.     return Io->iotd_Req.io_Error;
  88.     }
  89.     return 0;
  90. }
  91.  
  92. /*
  93.  * All checksums make the block add to 0.
  94.  */
  95. int
  96. CheckSum(ULONG *buffer)
  97. {
  98.     int         i;
  99.     ULONG        sum = 0;
  100.  
  101.     for (i = SIZE; i > 0; i--)
  102.     sum += *buffer++;
  103.  
  104.     return sum? 0 : 1;
  105. }
  106.  
  107. int
  108. GetBitmapExtBlock(ULONG blocknr)
  109. {
  110.     if (blocknr != BitmapExtBlockNr) {
  111.     ULONG        key;
  112.     ULONG        keynr;
  113.  
  114.     if (blocknr < BitmapExtBlockNr || BitmapExtBlockNr == (ULONG)-1) {
  115.         key = RootBlock[SIZE - 24];
  116.         keynr = 0;
  117.         if (Verbose >= 2)
  118.         printf("GetBitmapExtBlock %d -> first key %d\n", blocknr, key);
  119.     } else {
  120.         key = BitmapExtBlock[SIZE - 1];
  121.         keynr = BitmapExtBlockNr + 1;
  122.         if (Verbose >= 2)
  123.         printf("GetBitmapExtBlock %d -> next key %d\n", blocknr, key);
  124.     }
  125.  
  126.     while (key && keynr <= blocknr) {
  127.         GetKey(key, BitmapExtBlock);
  128.         BitmapExtBlockNr = keynr;
  129.         if (Verbose >= 2)
  130.         printf("GetBitmapExtBlock %d -> get %d key %d\n",
  131.             blocknr, keynr, key);
  132.         key = BitmapExtBlock[SIZE - 1];
  133.         keynr++;
  134.     }
  135.  
  136.     if (key == 0 && BitmapExtBlockNr != blocknr) {
  137.         debug0(("No bitmap extension block #%d!!!\n", keynr));
  138.         return -97;
  139.     }
  140.     }
  141.     return 0;
  142. }
  143.  
  144. int
  145. GetBitmapBlock(ULONG blocknr, ULONG *buffer)
  146. {
  147.     ULONG        key;
  148.  
  149.     if (blocknr < BM_BLOCKS_PER_ROOTBLOCK) {
  150.     key = RootBlock[SIZE - 49 + blocknr];
  151.     if (Verbose >= 2)
  152.         printf("GetBitmapBlock %d -> root key %d\n", blocknr, key);
  153.     } else {
  154.     ULONG        tmp =    blocknr - BM_BLOCKS_PER_ROOTBLOCK;
  155.     ULONG        bmeblocknr = tmp / BM_BLOCKS_PER_BMEBLOCK;
  156.     ULONG        offset       = tmp % BM_BLOCKS_PER_BMEBLOCK;
  157.  
  158.     if (Verbose >= 2)
  159.         printf("GetBitmapBlock %d -> extension block %d\n", blocknr, bmeblocknr);
  160.  
  161.     if ((tmp = GetBitmapExtBlock(bmeblocknr)) == 0)
  162.         key = BitmapExtBlock[offset];
  163.     else
  164.         return tmp;
  165.  
  166.     if (Verbose >= 2)
  167.         printf("GetBitmapBlock %d -> (ext'd) key %d\n", blocknr, key);
  168.     }
  169.     if (key == 0) {
  170.     debug0(("Key for BitmapBlock #%d is 0.\n", blocknr));
  171.     return -98;
  172.     }
  173.     if (GetKey(key, buffer) == 0) {
  174.     if (CheckSum(buffer) == 0) {
  175.         printf("Checksum of Bitmap Block #%d, key %d is bad!\n",
  176.            blocknr, key);
  177.         return -99;
  178.     }
  179.     return 0;
  180.     }
  181.     return Io->iotd_Req.io_Error;
  182. }
  183.  
  184. int
  185. GetBit(ULONG key)
  186. {
  187.     ULONG        blocknr;
  188.  
  189.     key -= De.de_Reserved;
  190.     blocknr = key / BitsPerBitmapBlock;
  191.  
  192.     if (blocknr != BitmapBlockNr) {
  193.     if (Verbose >= 2)
  194.         printf("GetBit %d -> BitmapBlock %d\n", key+De.de_Reserved, blocknr);
  195.  
  196.     if (blocknr == BitmapBlockNr + 1)
  197.         memcpy(BitmapBlock + 1, BitmapBlock + SIZE, (SIZE - 1) * 4);
  198.     else
  199.         GetBitmapBlock(blocknr, BitmapBlock);
  200.     if (GetBitmapBlock(blocknr + 1, BitmapBlock + SIZE) == 0) {
  201.         memmove(BitmapBlock + SIZE, BitmapBlock + SIZE + 1, (SIZE - 1) * 4);
  202.     } else {
  203.         memset(BitmapBlock + SIZE, 0, SIZE * 4);
  204.         debug0(("Zeroed 2nd bitmapblock.\n"));
  205.     }
  206.     BitmapBlockNr = blocknr;
  207.     }
  208.  
  209.     return key % BitsPerBitmapBlock;        /* bit offset */
  210. }
  211.  
  212. void
  213. ZeroOut(int key)
  214. {
  215.     debug0(("ZeroOut %d.\n", key));
  216.     SectorsCleared++;
  217.  
  218.     if (GetKey(key, ZeroBlock) == 0) {
  219.     int        i;
  220.     ULONG           *p;
  221.  
  222.     for (i = SIZE, p = ZeroBlock; i > 0; i--, p++) {
  223.         if (*p != 0) {
  224.         for (; i > 0; i--, p++)
  225.             *p = 0;
  226.         if (!Pretend)
  227.             PutKey(key, ZeroBlock);
  228.         SectorsReallyCleared++;
  229.         break;
  230.         }
  231.     }
  232.     }
  233. }
  234.  
  235. void
  236. ZeroTrack(int track)
  237. {
  238.     char        name[64];
  239.     ULONG        i;
  240.  
  241.     TracksDeleted++;
  242.     i = sprintf(name, XPKDISKDIR "Unit%lx/", Fssm.fssm_Unit);
  243.     NewName(&name[i], track);
  244.     if (i = Lock(name, SHARED_LOCK)) {
  245.     UnLock(i);
  246.     TracksReallyDeleted++;
  247.     printf("Delete %s.\n", name);
  248.     if (!Pretend)
  249.         DeleteFile(name);
  250.     }
  251. }
  252.  
  253. LONG
  254. min(LONG a, LONG b)
  255. {
  256.     return a < b? a: b;
  257. }
  258.  
  259. void
  260. CheckBits(int bitoffset, int numbits, ULONG key, int track)
  261. {
  262.     int         longindex;
  263.     int         longoffset;
  264.     int         bits;
  265.     ULONG       *p;
  266.     char        ones = 0;
  267.     char        zeros = 0;
  268.     ULONG        mask;
  269.     int         pass;
  270.     ULONG        mykey;
  271.  
  272.     if (Verbose >= 1) {
  273.     printf(" Track %5d... ", track);
  274.     }
  275.  
  276.     if (key == De.de_Reserved) {
  277.     /* Pretend the reserved sectors are in use */
  278.     zeros = 1;
  279.     }
  280.  
  281.     for (pass = 0 + !XpkDisk; pass < 2; pass++) {
  282.     longindex = bitoffset / 32;
  283.     longoffset = bitoffset % 32;
  284.     bits = numbits;
  285.     mykey = key;
  286.  
  287.     p = BitmapBlock + 1 + longindex;
  288.     mask = 1L << longoffset;
  289.     debug0(("Start %08lx, track %d, pass %d, mask %08lx, bits %d\n",
  290.            *p, track, pass, mask, bits));
  291.  
  292.     while (bits > 0) {
  293.         if (*p == 0xFFFFFFFF) {
  294.         if (pass > 0) {
  295.             int i = min(32-1-longoffset, bits-1);
  296.  
  297.             debug0(("bits %d, *p %x, mykey %d: ", bits, *p, mykey));
  298.             for (; i >= 0; i--) {
  299.             ZeroOut(mykey + i);
  300.             }
  301.         }
  302.         bits -= 32 - longoffset;
  303.         mask = 1;
  304.         mykey += 32 - longoffset;
  305.         longoffset = 0;
  306.         p++;
  307.         debug0(("Next  %08lx, track %d, pass %d, bits %d\n", *p, track, pass, bits));
  308.         ones = 1;
  309.         } else if (*p == 0) {
  310.         bits -= 32 - longoffset;
  311.         mask = 1;
  312.         mykey += 32 - longoffset;
  313.         longoffset = 0;
  314.         p++;
  315.         debug0(("Next  %08lx, track %d, pass %d, bits %d\n", *p, track, pass, bits));
  316.         zeros = 1;
  317.         } else {
  318.         if (*p & mask) {
  319.             /* Block free */
  320.             ones = 1;
  321.             if (pass > 0) {
  322.             debug0(("%08lx ", *p));
  323.             ZeroOut(mykey);
  324.             }
  325.         } else {
  326.             /* Block in use */
  327.             zeros = 1;
  328.         }
  329.  
  330.         bits--;
  331.         mask <<= 1;
  332.         mykey++;
  333.         if (mask == 0) {
  334.             longoffset = 0;
  335.             mask = 1;
  336.             p++;
  337.             debug0(("Next  %08lx, track %d, pass %d, bits %d\n", *p, track, pass, bits));
  338.         }
  339.         }
  340.     }
  341.     if (!ones || !zeros)
  342.         break;
  343.     }
  344.     if (Verbose) {
  345.     printf("%c\r", ones ? 'Z' : ' ');
  346.     fflush(stdout);
  347.     }
  348.     if (XpkDisk && !zeros)
  349.     ZeroTrack(track);
  350. }
  351.  
  352. void
  353. Clear(void)
  354. {
  355.     ULONG        key;
  356.     ULONG        nextkey;
  357.     ULONG        track;
  358.  
  359.     /* First, test the boot block for file system type */
  360.     GetKey(0, RootBlock);
  361.     if ((RootBlock[0] & 0xFFFFFF00) != 'DOS\0') {
  362.     printf("Not an AmigaDOS disk.\n");
  363.     return;
  364.     }
  365.  
  366.     /* Start at rootblock */
  367.     GetKey(RootBlockKey, RootBlock);
  368.     if (RootBlock[0] != 2 || RootBlock[SIZE-1] != ST_ROOT) {
  369.     printf("Rootblock is not a root block.\n");
  370.     return;
  371.     }
  372.     if (!CheckSum(RootBlock)) {
  373.     printf("Rootblock checksum bad.\n");
  374.     return;
  375.     }
  376.     if (RootBlock[SIZE - 50] == 0) {
  377.     printf("Bitmap valid flag not set.\n");
  378.     return;
  379.     }
  380.  
  381.     key = De.de_Reserved;
  382.     track = key / De.de_BlocksPerTrack;
  383.     nextkey = (track + 1) * De.de_BlocksPerTrack;
  384.  
  385.     CheckBits(GetBit(key), nextkey - key, key, track);
  386.  
  387.     track++;
  388.     key = nextkey;
  389.  
  390.     for (; key < MaxKey; key = nextkey, track++) {
  391.     int        offset;
  392.  
  393.     nextkey = key + De.de_BlocksPerTrack;
  394.     offset = GetBit(key);
  395.     CheckBits(offset, De.de_BlocksPerTrack, key, track);
  396.     chkabort();
  397.     }
  398. }
  399.  
  400. int
  401. OpenAll(char *devicename)
  402. {
  403.     int         fail = 0;
  404.  
  405.     {
  406.     struct DosList *dl;
  407.  
  408.     if (dl = LockDosList(LDF_DEVICES | LDF_READ)) {
  409.         if (dl = FindDosEntry(dl, devicename, LDF_DEVICES)) {
  410.         struct FileSysStartupMsg *fssm;
  411.         struct DosEnvec *de;
  412.  
  413.         fssm = BADDR(dl->dol_misc.dol_handler.dol_Startup);
  414.         de = BADDR(fssm->fssm_Environ);
  415.  
  416.         Fssm = *fssm;
  417.         Fssm.fssm_Device = (char *)BADDR(Fssm.fssm_Device) + 1;
  418.         De = *de;
  419.         HandlerPort = dl->dol_Task;
  420.         } else {
  421.         printf("No %s.\n", devicename);
  422.         fail = 1;
  423.         }
  424.         UnLockDosList(LDF_DEVICES | LDF_READ);
  425.     } else {
  426.         printf("Can't LockDosList.\n");
  427.         fail = 2;
  428.     }
  429.     }
  430.     if (fail != 0)
  431.     return fail;
  432.  
  433.     if (HandlerPort) {
  434.     DoPkt(HandlerPort, ACTION_FLUSH, 0, 0, 0, 0, 0);
  435.     DoPkt(HandlerPort, ACTION_INHIBIT, -1, 0, 0, 0, 0);
  436.     }
  437.  
  438.     if (De.de_TableSize < DE_BUFMEMTYPE)
  439.     De.de_BufMemType = MEMF_CHIP | MEMF_PUBLIC;
  440.  
  441.     Port = CreateMsgPort();
  442.     if (Port == NULL)
  443.     return 3;
  444.  
  445.     Io = CreateExtIO(Port, sizeof(*Io));
  446.     if (Io == NULL)
  447.     return 4;
  448.  
  449.     if (fail = OpenDevice((char *)Fssm.fssm_Device, Fssm.fssm_Unit,
  450.            (struct IORequest *)Io, Fssm.fssm_Flags)) {
  451.     printf("Can't OpenDevice %s unit %d, error %d.\n",
  452.            Fssm.fssm_Device, Fssm.fssm_Unit, fail);
  453.     return 5;
  454.     }
  455.  
  456.     Io->iotd_Req.io_Command = TD_CHANGENUM;
  457.     DoIO((struct IORequest *)Io);
  458.     Io->iotd_Count = Io->iotd_Req.io_Actual;
  459.  
  460.     XpkDisk = strcmp(FilePart((char *)Fssm.fssm_Device), "xpkdisk.device") == 0;
  461.  
  462.     RootBlock = AllocMem(SIZE * sizeof(ULONG), De.de_BufMemType);
  463.     if (RootBlock == NULL)
  464.     return 6;
  465.  
  466.     BitmapBlock = AllocMem(2 * SIZE * sizeof(ULONG), De.de_BufMemType);
  467.     if (BitmapBlock == NULL)
  468.     return 7;
  469.  
  470.     BitmapExtBlock = AllocMem(SIZE * sizeof(ULONG), De.de_BufMemType);
  471.     if (BitmapExtBlock == NULL)
  472.     return 8;
  473.  
  474.     ZeroBlock = AllocMem(SIZE * sizeof(ULONG), De.de_BufMemType);
  475.     if (ZeroBlock == NULL)
  476.     return 9;
  477.  
  478.     Offset = sizeof(ULONG) * SIZE *
  479.          De.de_BlocksPerTrack * De.de_Surfaces * De.de_LowCyl;
  480.     MaxKey = De.de_BlocksPerTrack * De.de_Surfaces *
  481.             (De.de_HighCyl - De.de_LowCyl + 1);
  482.     RootBlockKey = (MaxKey - 1 + De.de_Reserved) / 2;
  483.  
  484.     BitsPerBitmapBlock = 32 * (SIZE - 1);
  485.  
  486.     debug0(("Offset %x, RootBlockKey %d\n", Offset, RootBlockKey));
  487.     debug0(("Bits/BitmapBlock %d\n", BitsPerBitmapBlock));
  488.  
  489.     if (De.de_BlocksPerTrack > BitsPerBitmapBlock) {
  490.     printf(
  491. "What a funny disk you have! %d blocks/track is more than I can handle!\n",
  492.         De.de_BlocksPerTrack);
  493.     return 10;
  494.     }
  495.  
  496.     return 0;
  497. }
  498.  
  499. void
  500. CloseAll(void)
  501. {
  502.     if (RootBlock)
  503.     FreeMem(RootBlock, SIZE * sizeof(unsigned long));
  504.     if (BitmapBlock)
  505.     FreeMem(BitmapBlock, 2 * SIZE * sizeof(unsigned long));
  506.     if (BitmapExtBlock)
  507.     FreeMem(BitmapExtBlock, SIZE * sizeof(unsigned long));
  508.     if (ZeroBlock)
  509.     FreeMem(ZeroBlock, SIZE * sizeof(unsigned long));
  510.     if (Io) {
  511.     if (Io->iotd_Req.io_Device) {
  512.         Io->iotd_Req.io_Command = ETD_UPDATE;
  513.         DoIO((struct IORequest *)Io);
  514.         Io->iotd_Req.io_Command = TD_MOTOR;
  515.         Io->iotd_Req.io_Length = 0;
  516.         DoIO((struct IORequest *)Io);
  517.         CloseDevice((struct IORequest *)Io);
  518.     }
  519.     DeleteExtIO((struct IORequest *)Io);
  520.     }
  521.     if (Port)
  522.     DeleteMsgPort(Port);
  523.     if (HandlerPort) {
  524.     DoPkt(HandlerPort, ACTION_INHIBIT, 0, 0, 0, 0, 0);
  525.     }
  526.  
  527.     printf(
  528. "Statistics: %d (%d) sectors (really) cleared,\n"
  529. "            %d (%d) tracks (really) deleted, \n"
  530. "            %d free sectors total.\n",
  531.         SectorsCleared,
  532.         SectorsReallyCleared,
  533.         TracksDeleted,
  534.         TracksReallyDeleted,
  535.         SectorsCleared + TracksDeleted * De.de_BlocksPerTrack);
  536. }
  537.  
  538. int
  539. main(int argc, char **argv)
  540. {
  541.     char       *colon;
  542.     int         ac;
  543.     char      **av;
  544.  
  545.     if (DOSBase->dl_lib.lib_Version < 37) {
  546.     printf("Sorry, requires 2.04+ (V37+)\n");
  547.     return 20;
  548.     }
  549.  
  550.     ac = argc - 1;
  551.     av = argv + 1;
  552.  
  553.     while (ac > 0 && av[0][0] == '-') {
  554.     char           *a = av[0] + 1;
  555.  
  556.     while (a[0]) {
  557.         switch (a[0]) {
  558.         case 'n':
  559.         Pretend = 1;
  560.         printf("Pretend mode.\n");
  561.         break;
  562.         case 'v':
  563.         Verbose++;
  564.         break;
  565.         default:
  566.         goto usage;
  567.         }
  568.         a++;
  569.     }
  570.     ac--;
  571.     av++;
  572.     }
  573.  
  574.     if (ac < 1) {
  575.     usage:
  576.     printf("Usage: %s [-n] [-v] devicename\n", argv[0]);
  577.     return 20;
  578.     }
  579.  
  580.     if (colon = strchr(av[0], ':'))
  581.     *colon = '\0';
  582.  
  583.     atexit(CloseAll);
  584.  
  585.     if (OpenAll(av[0]) == 0) {
  586.     if (!Pretend) {
  587.         printf("Hit return to commence clearing %s: or CTRL-C to abort: ",
  588.             av[0]);
  589.         fflush(stdout);
  590.         while (!feof(stdin) && getchar() != '\n')
  591.         /* nothing */ ;
  592.         chkabort();
  593.     }
  594.     Clear();
  595.     }
  596.     /*CloseAll();*/
  597. }
  598.